<?php

class FormGenerationHelper {

    public static function generateForm($form_name, $force_overwrite = false) {
        $forms = self::getAllForms();
        if (!isset($forms[$form_name])) {
            print $form_name . " NOT FOUND\n";
            return;
        }
        print "Generating:{$form_name}\n";
        $ini = SCIniHelper::parseIniFile($ini_path = $forms[$form_name]);
        $dir_path = dirname($ini_path);
        $labels = array();
        $fields = isset($ini['fields']) ? $ini['fields'] : array();
        foreach ($fields as $key => $field) {
            if (!preg_match("/FormField$/", $fields[$key]['type']))
                $fields[$key]['type'] = $fields[$key]['type'] . "FormField";
        }
        //<editor-fold defaultstate="collapsed" desc="Form.class">
        if (!file_exists($file_path = "{$dir_path}/{$form_name}.php") || $force_overwrite) {
            self::file_put_contents($file_path, <<<PHP
<?php

class {$form_name} extends Form {

    public function Create() {
        //..
        return parent::Create();
    }

}
PHP
            );
        }
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.html">
        if (!file_exists($file_path = "{$dir_path}/{$form_name}.html") || $force_overwrite) {
            $fields_content = array();
            foreach ($fields as $field_name => $field) {
                $field_name_uppercase = strtoupper($field_name);
                $labels[$field_name_uppercase] = $field_name_uppercase;
                $options_content = array();
                if (in_array($field['type'], array('RadioFormField', 'CheckboxFormField'))) {
                    if (isset($field['properties']['Options'])) {
                        $options = $field['properties']['Options'];
                        foreach ($options as $option_key => $option_value) {
                            $options_content[] = "{$option_value}:{\$field.{$field_name}->RenderOption('{$option_key}')}";
                        }
                    }
                } else {
                    $options_content[] = "{\$field.{$field_name}}";
                }
                $options_content_joined = join(" - ", $options_content);
                $fields_content[] = <<<HTML
        <tr>
            <td>{\$label.{$field_name_uppercase}}</td>
            <td>{$options_content_joined}</td>
            <td><div data-error-label="{\$field.{$field_name}->getControlFullName()}"/></td>
        </tr>
HTML;
            }
            $fields_content[] = <<<HTML
        <tr>
            <td>{\$field.Submit}</td>
            <td>{\$field.Reset}</td>
            <td></td>
        </tr>
HTML;
            $fields_content_joined = join("\n", $fields_content);
            self::file_put_contents($file_path, <<<HTML
<form {\$mattrs}>
    <table>
{$fields_content_joined}
    </table>
</form>
HTML
            );
        }
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.fields_collection">
        if (!file_exists($file_path = "{$dir_path}/{$form_name}_FieldCollection.php") || $force_overwrite) {
            self::file_put_contents($file_path, <<<PHP
<?php

class {$form_name}_FieldCollection extends {$form_name}_FieldCollectionBase {

}
PHP
            );
        }
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.fields_collection_base">
        $file_path = "{$dir_path}/{$form_name}_FieldCollectionBase.php";
        $fields_content = array();
        $fields_create_content = array();
        foreach ($fields as $field_name => $field) {
            $validators = isset($field['validators']) && is_array($field['validators']) ? $field['validators'] : array();

            $validators_content = array();
            foreach ($validators as $validator_name => $validator) {
                switch ($validator) {
                    case FormFieldValidator::VALIDATOR_TYPE_REQUIRED:
                        $validators_content[] = "new RequiredFormFieldValidator()";
                        break;
                    default:
                        throw new Exception("Unknown FormFieldValidator type");
                        break;
                }
            }
            $validators_content_joined = join(",\n", $validators_content);


            $properties = isset($field['properties']) && is_array($field['properties']) ? $field['properties'] : array();
            $properties_content_joined = "";
            if (count($properties) > 0) {
                $properties_content = array("\$this->_$field_name");
                foreach ($properties as $property_name => $property_value)
                    $properties_content[] = "set{$property_name}(" . var_export($property_value, true) . ")";

                $properties_content_joined = join("->", $properties_content) . ";";
            }


            $field_name_uppercase = strtoupper($field_name);
            $fields_content[] = <<<PHP
    //<editor-fold defaultstate="collapsed" desc="{$field_name}">
    /**
     * @var {$field['type']}
     */
    private \$_{$field_name} = null;

    /**
     *
     * @return {$field['type']}
     */
    public function get{$field_name}() {
        if (\$this->_{$field_name} === null) {
            \$this->_{$field_name} = \$this->AddFormField('{$field_name}', '{$field['type']}',{$form_name}_Labels::{$field_name_uppercase},array(
                {$validators_content_joined}
            ));
            $properties_content_joined
        }
        return \$this->_{$field_name};
    }
    //</editor-fold>        
PHP;
            $fields_create_content[] = <<<PHP
        \$this->get{$field_name}();
PHP;
        }
        $fields_create_content[] = <<<PHP
        \$this->getSubmitButton();
        \$this->getResetButton();
PHP;
        $fields_content_joined = join("\n", $fields_content);
        $fields_create_content_joined = join("\n", $fields_create_content);

        self::file_put_contents($file_path, <<<PHP
<?php

class {$form_name}_FieldCollectionBase extends FormFieldCollection {
{$fields_content_joined}
    public function Create() {
{$fields_create_content_joined}
        return parent::Create();
    }
}
PHP
        );

        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.labels">
        if (!file_exists($file_path = "{$dir_path}/labels/"))
            mkdir($file_path, 0744);
        if (!file_exists($file_path = "{$dir_path}/labels/sc.php") || $force_overwrite) {
            $labels_content = array();
            foreach ($labels as $label_name => $label) {
                $label_name_uppercase = strtoupper($label_name);
                $labels_content[] = "   const {$label_name} = '{$label}'; ";
            }
            $labels_content_joined = join("\n", $labels_content);
            self::file_put_contents($file_path, <<<PHP
<?php

class {$form_name}_Labels extends ComponentLabels {
{$labels_content_joined}
}
PHP
            );
        }

        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.js">
        if ((!file_exists($file_path = "{$dir_path}/{$form_name}.js") || $force_overwrite) && isset($ini['js'])) {
            self::file_put_contents($file_path, <<<JS
{$form_name} = sCore.makeClass(Form,{
    init : function() {
        {$form_name}.parentClass.init.apply(this,arguments);
    },
    create : function() {
        {$form_name}.parentClass.create.apply(this,arguments);
    }
});

JS
            );
        }
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.less.css">
        if ((!file_exists($file_path = "{$dir_path}/{$form_name}.less.css") || $force_overwrite) && isset($ini['less'])) {
            $fields_content = array();
            foreach ($fields as $field_name => $field) {
                $fields_content[] = <<<CSS
   input.{$field_name} {
       
   }
CSS;
            }
            $fields_content_joined = join("\n", $fields_content);
            self::file_put_contents($file_path, <<<CSS
form.{$form_name} {
{$fields_content_joined}
}
CSS
            );
        }
        //</editor-fold>
        //<editor-fold defaultstate="collapsed" desc="Form.css">
        if ((!file_exists($file_path = "{$dir_path}/{$form_name}.css") || $force_overwrite) && isset($ini['css'])) {
            $fields_content = array();
            foreach ($fields as $field_name => $field) {
                $fields_content[] = <<<CSS
form.{$form_name} .{$field_name} {

}
CSS;
            }
            $fields_content_joined = join("\n", $fields_content);
            self::file_put_contents($file_path, $fields_content_joined);
        }
        //</editor-fold>
    }

    private static function file_put_contents($filename, $contents) {
        file_put_contents($filename, $contents);
    }

    private static $_AllForms;

    public static function getAllForms() {
        if (self::$_AllForms === null) {
            self::$_AllForms = array();
            if (file_exists($forms_path = SCORE_APP_PATH . "lib/php/web/forms/")) {
                if (count($files = scandir($forms_path)) > 0) {
                    foreach ($files as $file) {
                        if ($file == '.' || $file == '..')
                            continue;
                        if (is_dir($full_path = $forms_path . $file) && file_exists($ini_path = $full_path . "/{$file}.ini")) {
                            self::$_AllForms[$file] = $ini_path;
                        }
                    }
                }
            }
        }
        return self::$_AllForms;
    }

}